package dragon

import (
	"http"
	"os"
	"time"
	"strconv"
	"fmt"

	"gorilla.googlecode.com/hg/gorilla/sessions"
        "github.com/russross/blackfriday"

	"appengine"
	"appengine/datastore"
)

func check(err os.Error, w http.ResponseWriter) {
	if err != nil {
		http.Error(w, err.String(), http.StatusInternalServerError)
		os.Exit(1)
	}
}

func isDigit(c byte) bool {
	return '0' <= c && c <= '9'
}

func isAllDigits(s string) bool {
	for k := range s {
		if !isDigit(s[k]) {
			return false
		}
	}
	return true
}

func prettyDate(date *time.Time) string {
        var s string

        switch date.Weekday {
        case time.Monday: s += "poniedziałek"
        case time.Tuesday: s += "wtorek"
        case time.Wednesday: s += "środa"
        case time.Thursday: s += "czwartek"
        case time.Friday: s += "piątek"
        case time.Saturday: s += "sobota"
        case time.Sunday: s += "niedziela"
        }

        s += ", " + strconv.Itoa(date.Day) + " "

        switch date.Month {
        case 1: s += "stycznia"
        case 2: s += "lutego"
        case 3: s += "marca"
        case 4: s += "kwietnia"
        case 5: s += "maja"
        case 6: s += "czerwca"
        case 7: s += "lipca"
        case 8: s += "sierpnia"
        case 9: s += "września"
        case 10: s += "października"
        case 11: s += "listopada"
        case 12: s += "grudnia"
        }

        s += " " + strconv.Itoa64(date.Year) + " roku, "
        s += fmt.Sprintf("%d:%02d", date.Hour, date.Minute)

        return s
}

func stuffDate() string {
        var s string

	date := time.LocalTime()

        switch date.Weekday {
        case time.Monday: s += "poniedziałek"
        case time.Tuesday: s += "wtorek"
        case time.Wednesday: s += "środa"
        case time.Thursday: s += "czwartek"
        case time.Friday: s += "piątek"
        case time.Saturday: s += "sobota"
        case time.Sunday: s += "niedziela"
        }

        s += ", " + strconv.Itoa(date.Day) + " "

        switch date.Month {
        case 1: s += "stycznia"
        case 2: s += "lutego"
        case 3: s += "marca"
        case 4: s += "kwietnia"
        case 5: s += "maja"
        case 6: s += "czerwca"
        case 7: s += "lipca"
        case 8: s += "sierpnia"
        case 9: s += "września"
        case 10: s += "października"
        case 11: s += "listopada"
        case 12: s += "grudnia"
        }

        s += " " + strconv.Itoa64(date.Year) + " roku"

        return s
}

func markdownCommon(args ...interface{}) string {
        var b []byte
        ok := false

        htmlFlags := 0
        htmlFlags |= blackfriday.HTML_USE_XHTML
        htmlFlags |= blackfriday.HTML_USE_SMARTYPANTS
        htmlFlags |= blackfriday.HTML_SMARTYPANTS_FRACTIONS
        htmlFlags |= blackfriday.HTML_SMARTYPANTS_LATEX_DASHES
        renderer := blackfriday.HtmlRenderer(htmlFlags, "", "")

        extensions := 0
        extensions |= blackfriday.EXTENSION_NO_INTRA_EMPHASIS
        extensions |= blackfriday.EXTENSION_TABLES
        extensions |= blackfriday.EXTENSION_FENCED_CODE
        extensions |= blackfriday.EXTENSION_AUTOLINK
        extensions |= blackfriday.EXTENSION_STRIKETHROUGH
        extensions |= blackfriday.EXTENSION_SPACE_HEADERS
        extensions |= blackfriday.EXTENSION_HARD_LINE_BREAK

        if len(args) == 1 {
                b, ok = args[0].([]byte)
                b = blackfriday.Markdown(b, renderer, extensions)
        }
        if !ok {
                b = []byte(fmt.Sprint(args...))
                b = blackfriday.Markdown(b, renderer, extensions)
        }

        return string(b)
}

func markdownBasic(args ...interface{}) string {
        var b []byte
        ok := false

        if len(args) == 1 {
                b, ok = args[0].([]byte)
                b = blackfriday.MarkdownBasic(b)
        }
        if !ok {
                b = []byte(fmt.Sprint(args...))
                b = blackfriday.MarkdownBasic(b)
        }

        return string(b)
}

func selector(pages int, page int, link string) string {
	var sel string

	prev := page-1
	next := page+1

	if pages > 1 {
		sel = "<span id=\"selector\"><table><tr><td>"
		if page != pages && page != pages-1 {
			sel += link + strconv.Itoa(pages) + "\">pierwsze</a>"
		}
		sel += "</td><td>"
		if next <= pages {
			sel += link + strconv.Itoa(next) + "\">poprzednie</a>"
		}
		sel += "</td><td>"
		if prev > 0 {
			sel += link + strconv.Itoa(prev) + "\">następne</a>"
		}
		sel += "</td><td>"
		if page != 1 && page != 2 {
			sel += link + "1\">ostatnie</a>"
		} 
		sel += "</td></tr></table><hr></span>"
	}
	
        return sel
}

func addCounter(kind string, c appengine.Context) {
	cs := &counters{
                Kind:    kind,
                Count:   0,
        }

	datastore.Put(c, datastore.NewIncompleteKey(c, "counters", nil), cs)
}

func updateCount(kind string, c appengine.Context, inc bool) {
	var css []*counters
	var count int

	q := datastore.NewQuery("counters").Filter("Kind =", kind).Limit(1)
	ks, _ := q.GetAll(c, &css)
	if len(ks) == 0 {
		addCounter(kind, c)
		ks, _ = q.GetAll(c, &css)
		if len(ks) == 0 {
			os.Exit(1)
			return
		}
	}
	datastore.DeleteMulti(c, ks)

	if inc == true {
		count = css[0].Count+1
	} else {
		count = css[0].Count-1
	}
	
	cs := &counters{
                Kind:	 kind,    
		Count:   count,
        }
	datastore.Put(c, ks[0], cs)
}

func count(c appengine.Context, r *http.Request, w http.ResponseWriter) string {
	var kind = "site"
	var cs []*counters

	if session, err := sessions.Session(r, "", "memcache"); err == nil {
		if session["on"] != 1 {
			updateCount(kind, c, true)
			session["on"] = 1
			sessions.Save(r, w)
		}
	}

	q := datastore.NewQuery("counters").Filter("Kind =", kind).Limit(1)
	csks, _ := q.GetAll(c, &cs)
	if len(csks) == 0 {
		addCounter(kind, c)
		q.GetAll(c, &cs)
	}

	return strconv.Itoa(cs[0].Count)
}

